<template>
  <el-dialog v-model="dialogVisible">
    <el-tree
      :data="treeData"
      show-checkbox
      :props="defaultProps"
      :default-expand-all="true"
      highlight-current
      ref="menuTree"
      node-key="id"
      :check-strictly="checkStrictly"
    />

    <template #footer>
      <el-button type="primary" @click="handleCheckAll">全部选择</el-button>
      <el-button type="warning" @click="handleSubmit">确认分配</el-button>
    </template>
  </el-dialog>
</template>

<script lang="ts" setup>
import type { IRole } from "@/api/role"
import { useMenuStore } from "@/stores/menu"
import type { PropType } from "vue"
import { ElTree } from "element-plus"
import Node from "element-plus/es/components/tree/src/model/node.mjs"
import { allocRoleAccess, getRoleAccess } from "@/api/roleAccess"
import { useReloadPage } from "@/hooks/useReloadPage"

const checkStrictly = ref(false)
const { reloadPage } = useReloadPage()
// 菜单store 拿到所有菜单数据
const store = useMenuStore()
const treeData = computed(() => store.state.menuTreeData) // 所有的菜单
onMounted(() => {
  // 获取所有的菜单数据
  store.getAllMenuList()
})
// 定义 el-tree 的 节点
const defaultProps = {
  children: "children",
  label: "title"
}
type ElTreeInstance = InstanceType<typeof ElTree>
// el-tree 的组件实例
const menuTree = ref<ElTreeInstance | null>(null)
// 是否全选状态
const isCheckAll = ref(false)
// 全部选择
const handleCheckAll = () => {
  checkStrictly.value = false
  setTimeout(() => {
    if (!isCheckAll.value) {
      menuTree.value?.setCheckedNodes(
        treeData.value as unknown as Node[],
        false
      )
    } else {
      menuTree.value?.setCheckedNodes([], false)
    }
    isCheckAll.value = !isCheckAll.value
  })
}
const { proxy } = getCurrentInstance()!
// 确认提交
const handleSubmit = async () => {
  const tree = menuTree.value!
  // 	若节点可用被选中 (show-checkbox 为 true), 它将返回当前选中节点 key 的数组
  const keys = tree.getCheckedKeys(false)
  // 若节点可被选中(show-checkbox 为 true)，则返回目前半选中的节点的 key 所组成的数组
  const halfKeys = tree.getHalfCheckedKeys()
  const selectKeys = [...keys, ...halfKeys]
  // 更新 角色对应的权限
  const res = await allocRoleAccess(role.id, selectKeys as number[])
  if (res.code === 0) {
    proxy?.$message.success("权限分配成功")
    // 刷新页面
    reloadPage()
  }
}

const { role, modelValue } = defineProps({
  role: {
    type: Object as PropType<IRole>,
    required: true
  },
  modelValue: {
    type: Boolean,
    default: false
  }
})
const dialogVisible = ref(modelValue)
const emit = defineEmits(["update:modelValue"])

watch(
  () => dialogVisible.value,
  (newValue) => {
    emit("update:modelValue", newValue)
  }
)
// 获取角色对应的权限，返显
const getRoleAccessList = async () => {
  // 在显示复选框的情况下，是否严格的遵循父子不互相关联的做法，默认为 false
  // 先解除严格关系，不然数据返显，半选状态下会有问题
  checkStrictly.value = true
  const res = await getRoleAccess(role.id)

  /* 
    console.log(res) 打印结果

    [
      { id: 73, role_id: 2, access_id: 37 },
      { id: 74, role_id: 2, access_id: 34 },
      { id: 75, role_id: 2, access_id: 35 },
      { id: 76, role_id: 2, access_id: 36 },
      { id: 77, role_id: 2, access_id: 39 },
    ]
    */

  if (res.statusCode === 200) {
    const access = res.data.map((item) => item.id)

    menuTree.value?.setCheckedKeys(access)
    // 返显完毕后，恢复，setTimeout
    setTimeout(() => {
      checkStrictly.value = false
    }, 0)
  }
  //
}

onMounted(() => {
  console.log("----")
  getRoleAccessList()
})
</script>
